package com.second.sixoo;

import com.github.rholder.retry.Retryer;
import com.github.rholder.retry.RetryerBuilder;
import com.github.rholder.retry.StopStrategies;
import com.github.rholder.retry.WaitStrategies;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.TimeUnit;

public class RedisStore {

    /**
     * 日志记录
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(RedisStore.class);
    private static Properties props = new Properties();

    public static final String REDIS_CLUSTER_NODE_PORT = "cluster.node.port";
    public static final String REDIS_MAX_TOTAL = "max.total";
    public static final String REDIS_MAX_IDLE = "max.idle";
    public static final String REDIS_MAX_WAIT_MILLIS = "max.wait.millis";
    public static final String REDIS_AUTH_CODE = "auth.code";

    public static void loadProp(String name) throws Exception {
        String CONF_DIR = System.getProperty("PROJECT_CONF_DIR");
        try {
            if (CONF_DIR == null || CONF_DIR.isEmpty()) {
                props.load(RedisStore.class.getClassLoader().getResourceAsStream(name));
            } else {
                String path = CONF_DIR + File.separator + name;
                props.load(new FileInputStream(path));
            }
        } catch (Exception e) {
            throw new Exception("加载" + name + "配置文件失败！conf_dir=" + CONF_DIR, e);
        }
    }

    public static Jedis createJedisCluterInstance() {
        String[] hostPortStr = String.valueOf(props.get(REDIS_CLUSTER_NODE_PORT)).split(":");
        GenericObjectPoolConfig config = new GenericObjectPoolConfig();
        config.setMaxTotal(Integer.valueOf(String.valueOf(props.get(REDIS_MAX_TOTAL))));
        config.setMaxIdle(Integer.valueOf(String.valueOf(props.get(REDIS_MAX_IDLE))));
        config.setMaxWaitMillis(Integer.valueOf(String.valueOf(props.get(REDIS_MAX_WAIT_MILLIS))));

        JedisPool jedisPool = new JedisPool(config, hostPortStr[0], Integer.valueOf(hostPortStr[1]));

        final Jedis[] jedis = {null};

        Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()
                .retryIfException()
                .withWaitStrategy(WaitStrategies.fixedWait(1000, TimeUnit.MILLISECONDS))
                .withStopStrategy(StopStrategies.stopAfterAttempt(10))
                .build();
        try {
            retryer.call(() -> {
                jedis[0] = jedisPool.getResource();
                jedis[0].auth(String.valueOf(props.get(REDIS_AUTH_CODE)));
                String value = jedis[0].ping();
                return StringUtils.isNotBlank(value);
            });
        } catch (Exception e) {
            LOGGER.error("多次获取Redis连接失败！");
        }
        return jedis[0];
    }


    public static void main(String[] args) throws Exception {
        loadProp("redis.properties");
        Jedis jedis = createJedisCluterInstance();
        Map<String, Double> sm = new HashMap(60000);
        long start = System.currentTimeMillis();
        long f = 0;
        for (int j = 0; j < 300; j++) {
            for (int i = 0; i < 120000; i++) {
                Double score = start + i * 1d;
                String mem = (start + i) + ":" + 12.345;
                sm.put(mem, score);
            }
            long s1 = System.currentTimeMillis();
            jedis.zadd("p" + j, sm);
            long e1 = System.currentTimeMillis();
            f = e1 - s1 + f;
            System.out.println(j + "=>耗时：" + (e1 - s1) + ",累计耗时：" + f / 1000);
        }
        System.out.println("最终耗时：" + f / 1000);


    }


    public static void clean(final Object buffer) throws Exception {
        AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {
                try {
                    Method getCleanerMethod = buffer.getClass().getMethod("cleaner", new Class[0]);
                    getCleanerMethod.setAccessible(true);
                    sun.misc.Cleaner cleaner = (sun.misc.Cleaner) getCleanerMethod.invoke(buffer, new Object[0]);
                    cleaner.clean();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return null;
            }
        });

    }
}
